﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using AdoNet = System.Data;

namespace DataSet4Com
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    [ComDefaultInterface(typeof(IDataRow))]
    [Guid("A65CE1FF-11D6-4099-A51B-ED04CED927F1")]
    public class DataRow : IDataRow
    {
        private AdoNet.DataRow _adoNetRow;

        public DataRow() : this(null)
        {
        }

        public DataRow(AdoNet.DataRow adoNetRow)
        {
            if (adoNetRow == null)
                throw new ArgumentNullException("adoNetRow");
            else
                _adoNetRow = adoNetRow;
        }

        [ComVisible(false)]
        public AdoNet.DataRow AdoNetDataRow
        {
            get { return _adoNetRow; }
        }

        public bool HasErrors
        {
            get { return _adoNetRow.HasErrors; }
        }

        public string RowError 
        {
            get { return _adoNetRow.RowError; }
            set { _adoNetRow.RowError = value; }
        }

        public DataRowState RowState 
        {
            get { return (DataRowState)((int)_adoNetRow.RowState); }        
        }

        public DataTable Table 
        {
            get { return new DataTable(_adoNetRow.Table); } 
        }

        public object GetValueOfColumn(DataColumn column)
        {
            return _adoNetRow[column.AdoNetDataColumn];
        }

        public void SetValueOfColumn(DataColumn column, object value)
        {
            _adoNetRow[column.AdoNetDataColumn] = value;
        }

        public object GetValueOfColumnIndex(int columnIndex)
        {
            return _adoNetRow[columnIndex];
        }

        public void SetValueOfColumnIndex(int columnIndex, object value)
        {
            _adoNetRow[columnIndex] = value;
        }

        public object GetValue(string columnName)
        {
            return _adoNetRow[columnName];
        }

        public string GetValueAsGuid(string columnName)
        {
            if (_adoNetRow.IsNull(columnName))
                return string.Empty;

            Guid guid = (Guid)_adoNetRow[columnName];
            return guid.ToString();
        }
        
        public void SetValue(string columnName, object value)
        {
            _adoNetRow[columnName] = value;
        }

        public object GetValueVersionOfColumn(DataColumn column, DataRowVersion version)
        {
            return _adoNetRow[column.AdoNetDataColumn, (AdoNet.DataRowVersion)((int)version)];
        }

        public object GetValueVersionOfColumnIndex(int columnIndex, DataRowVersion version)
        {
            return _adoNetRow[columnIndex, (AdoNet.DataRowVersion)((int)version)];
        }
        
        public object GetValueVersion(string columnName, DataRowVersion version)
        {
            return _adoNetRow[columnName, (AdoNet.DataRowVersion)((int)version)];
        }

        public void AcceptChanges()
        {
            _adoNetRow.AcceptChanges();
        }

        public void BeginEdit()
        {
            _adoNetRow.BeginEdit();
        }

        public void CancelEdit()
        {
            _adoNetRow.CancelEdit();
        }

        public void ClearErrors()
        {
            _adoNetRow.ClearErrors();
        }

        public void Delete()
        {
            _adoNetRow.Delete();
        }

        public void EndEdit()
        {
            _adoNetRow.EndEdit();
        }

        public DataRowList GetChildRowsByRelation(DataRelation relation)
        {
            DataRow[] result = (from row in _adoNetRow.GetChildRows(relation.AdoNetDataRelation)
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public DataRowList GetChildRows(string relationName)
        {
            DataRow[] result = (from row in _adoNetRow.GetChildRows(relationName)
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public DataRowList GetChildRowsOfVersionByRelation(DataRelation relation, DataRowVersion version)
        {
            DataRow[] result = (from row in _adoNetRow.GetChildRows(relation.AdoNetDataRelation, (AdoNet.DataRowVersion)((int)version))
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public DataRowList GetChildRowsOfVersion(string relationName, DataRowVersion version)
        {
            DataRow[] result = (from row in _adoNetRow.GetChildRows(relationName, (AdoNet.DataRowVersion)((int)version))
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public string GetColumnErrorByColumn(DataColumn column)
        {
            return _adoNetRow.GetColumnError(column.AdoNetDataColumn);
        }

        public string GetColumnErrorByColumnIndex(int columnIndex)
        {
            return _adoNetRow.GetColumnError(columnIndex);
        }

        public string GetColumnError(string columnName)
        {
            return _adoNetRow.GetColumnError(columnName);
        }

        public DataColumnList GetColumnsInError()
        {
            DataColumn[] result = (from column in _adoNetRow.GetColumnsInError()
                                   select new DataColumn(column)).ToArray();

            return new DataColumnList(result);
        }

        public DataRow GetParentRowByRelation(DataRelation relation)
        {
            return new DataRow(_adoNetRow.GetParentRow(relation.AdoNetDataRelation));
        }

        public DataRow GetParentRow(string relationName)
        {
            return new DataRow(_adoNetRow.GetParentRow(relationName));
        }

        public DataRow GetParentRowOfVersionByRelation(DataRelation relation, DataRowVersion version)
        {
            return new DataRow(_adoNetRow.GetParentRow(relation.AdoNetDataRelation, (AdoNet.DataRowVersion)((int)version)));
        }

        public DataRow GetParentRowOfVersion(string relationName, DataRowVersion version)
        {
            return new DataRow(_adoNetRow.GetParentRow(relationName, (AdoNet.DataRowVersion)((int)version)));
        }

        public DataRowList GetParentRowsByRelation(DataRelation relation)
        {
            DataRow[] result = (from row in _adoNetRow.GetParentRows(relation.AdoNetDataRelation)
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public DataRowList GetParentRows(string relationName)
        {
            DataRow[] result = (from row in _adoNetRow.GetParentRows(relationName)
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public DataRowList GetParentRowsOfVersionByRelation(DataRelation relation, DataRowVersion version)
        {
            DataRow[] result = (from row in _adoNetRow.GetParentRows(relation.AdoNetDataRelation, (AdoNet.DataRowVersion)((int)version))
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public DataRowList GetParentRowsOfVersion(string relationName, DataRowVersion version)
        {
            DataRow[] result = (from row in _adoNetRow.GetParentRows(relationName, (AdoNet.DataRowVersion)((int)version))
                                select new DataRow(row)).ToArray();

            return new DataRowList(result);
        }

        public bool HasVersion(DataRowVersion version)
        {
            return _adoNetRow.HasVersion((AdoNet.DataRowVersion)((int)version));
        }

        public bool IsNullByColumn(DataColumn column)
        {
            return _adoNetRow.IsNull(column.AdoNetDataColumn);
        }

        public bool IsNullByColumnIndex(int columnIndex)
        {
            return _adoNetRow.IsNull(columnIndex);
        }

        public bool IsNull(string columnName)
        {
            return _adoNetRow.IsNull(columnName);
        }

        public bool IsVersionNull(DataColumn column, DataRowVersion version)
        {
            return _adoNetRow.IsNull(column.AdoNetDataColumn, (AdoNet.DataRowVersion)((int)version));
        }

        public void RejectChanges()
        {
            _adoNetRow.RejectChanges();
        }

        public void SetAdded()
        {
            _adoNetRow.SetAdded();
        }

        public void SetColumnErrorByColumn(DataColumn column, string error)
        {
            _adoNetRow.SetColumnError(column.AdoNetDataColumn, error);
        }

        public void SetColumnErrorByColumnIndex(int columnIndex, string error)
        {
            _adoNetRow.SetColumnError(columnIndex, error);
        }

        public void SetColumnError(string columnName, string error)
        {
            _adoNetRow.SetColumnError(columnName, error);
        }

        public void SetModified()
        {
            _adoNetRow.SetModified();
        }

        public void SetParentRow(DataRow parentRow)
        {
            _adoNetRow.SetParentRow(parentRow.AdoNetDataRow);
        }

        public void SetParentRowByRelation(DataRow parentRow, DataRelation relation)
        {
            _adoNetRow.SetParentRow(parentRow.AdoNetDataRow, relation.AdoNetDataRelation);
        }
    }

    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [Guid("38F85F18-39D6-468A-8972-773DED1E5A60")]
    public interface IDataRow
    {
        bool HasErrors { get; }
        
        string RowError { get; set; }
        
        DataRowState RowState { get; }
        
        DataTable Table { get; }

        object GetValueOfColumn(DataColumn column);
        void SetValueOfColumn(DataColumn column, object value);

        object GetValueOfColumnIndex(int columnIndex);
        void SetValueOfColumnIndex(int columnIndex, object value);

        object GetValue(string columnName);
        string GetValueAsGuid(string columnName);
        void SetValue(string columnName, object value);

        object GetValueVersionOfColumn(DataColumn column, DataRowVersion version);
        object GetValueVersionOfColumnIndex(int columnIndex, DataRowVersion version);
        object GetValueVersion(string columnName, DataRowVersion version);
                
        void AcceptChanges();
        
        void BeginEdit();
        
        void CancelEdit();
        
        void ClearErrors();
        
        void Delete();
        
        void EndEdit();
        
        DataRowList GetChildRowsByRelation(DataRelation relation);

        DataRowList GetChildRows(string relationName);

        DataRowList GetChildRowsOfVersionByRelation(DataRelation relation, DataRowVersion version);

        DataRowList GetChildRowsOfVersion(string relationName, DataRowVersion version);
        
        string GetColumnErrorByColumn(DataColumn column);
        
        string GetColumnErrorByColumnIndex(int columnIndex);
        
        string GetColumnError(string columnName);
        
        DataColumnList GetColumnsInError();
        
        DataRow GetParentRowByRelation(DataRelation relation);
        
        DataRow GetParentRow(string relationName);
        
        DataRow GetParentRowOfVersionByRelation(DataRelation relation, DataRowVersion version);
        
        DataRow GetParentRowOfVersion(string relationName, DataRowVersion version);

        DataRowList GetParentRowsByRelation(DataRelation relation);

        DataRowList GetParentRows(string relationName);

        DataRowList GetParentRowsOfVersionByRelation(DataRelation relation, DataRowVersion version);

        DataRowList GetParentRowsOfVersion(string relationName, DataRowVersion version);
        
        bool HasVersion(DataRowVersion version);
        
        bool IsNullByColumn(DataColumn column);
        
        bool IsNullByColumnIndex(int columnIndex);
        
        bool IsNull(string columnName);
        
        bool IsVersionNull(DataColumn column, DataRowVersion version);
        
        void RejectChanges();
        
        void SetAdded();
        
        void SetColumnErrorByColumn(DataColumn column, string error);
        
        void SetColumnErrorByColumnIndex(int columnIndex, string error);
        
        void SetColumnError(string columnName, string error);
        
        void SetModified();
        
        void SetParentRow(DataRow parentRow);
        
        void SetParentRowByRelation(DataRow parentRow, DataRelation relation);
    }
}
